/*
** malloc.c for  in /home/lund/Projets/mallocv2
** 
** Made by florian dewulf
** Login   <dewulf_f@epitech.net>
** 
** Started on  Tue Feb  5 11:09:43 2013 florian dewulf
** Last update Thu Feb  7 15:20:18 2013 florian dewulf
*/

#include	<unistd.h>
#include	<string.h>
#include	<pthread.h>
#include	"malloc.h"

extern t_malloc		*g_list;
static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;

void		*joint(t_malloc *ptr)
{
  t_malloc	*tmp;

  if (ptr && ptr->prev && (ptr->prev)->state == FALSE)
    {
      tmp = ptr->prev;
      tmp->next = ptr->next;
      if (ptr->next)
	ptr->next->prev = tmp;
      tmp->size += ptr->size + BLOCK;
      ptr = tmp;
    }
  if (ptr && ptr->next && ptr->next->state == FALSE)
    {
      tmp = ptr->next;
      ptr->next = tmp->next;
      if (ptr->next)
	ptr->next->prev = ptr;
      ptr->size += tmp->size + BLOCK;
    }
  if (ptr && ptr->next == NULL && ptr->state == FALSE)
    {
      (ptr->prev) ? (ptr->prev->next = NULL) : (g_list = NULL);
      return (sbrk(-(ptr->size + BLOCK)));
    }
  return (NULL);
}

void		*malloc(size_t size)
{
  t_malloc	*data;

  if (size == 0)
    return (NULL);
  pthread_mutex_lock(&mutex);
  size = get_size(size);
  //if ((data = separate(size)) == NULL)
  data = xsbrk(size);
  pthread_mutex_unlock(&mutex);
  if (data == ERROR)
    return (NULL);
  else
    return (data + 1);
}

void		free(void *ptr)
{
  t_malloc	*tmp;

  if (!ptr)
    return;
  pthread_mutex_lock(&mutex);
  tmp = search_maille(ptr);
  if (!tmp)
    {
      //write(2, "Bad Free\n", 9);
      pthread_mutex_unlock(&mutex);
      return;
    }
  tmp->state = FALSE;
  pthread_mutex_unlock(&mutex);
  if (joint(tmp) == ERROR)
    write(2, "Bad Free\n", 9);
}

void		*alloc(t_malloc *ptr, unsigned int size)
{
  void		*tmp;

  pthread_mutex_unlock(&mutex);
  tmp = malloc(size);
  if (tmp == NULL)
    return (ptr);
  if (ptr->size < size)
    memcpy(tmp, ptr + 1, ptr->size);
  else
    memcpy(tmp, ptr + 1, size);
  free(ptr);
  return (tmp);
}

void		*realloc(void *ptr, size_t size)
{
  t_malloc	*tmp;

  pthread_mutex_lock(&mutex);
  if (size == 0)
    {
      pthread_mutex_unlock(&mutex);
      if (ptr != NULL)
	free(ptr);
      return (NULL);
    }
  else if (ptr == NULL)
    {
      pthread_mutex_unlock(&mutex);
      return (malloc(size));
    }
  else
    {
      tmp = search_maille(ptr);
      if (!tmp)
	{
	  write(2, "Bad realloc\n", 12);
	  pthread_mutex_unlock(&mutex);
	  return (ptr);
	}
      return (get_maille(tmp, size));
    }
}
